
#include "Shell.h"
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <vector>
#include <map>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>



using namespace std;

pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
int  counter = 0;

//Local Methods

void start();
void *functionC();


Shell::Shell(){

}
Shell::~Shell(){

}

void Shell::createNet( string inputFile) {

    string line;
    ifstream inFile;

    inFile.open(inputFile.c_str());
    if (!inFile) {
            cout << "Unable to open file";
            exit(1); // terminate with error
    }

    inFile >> _bufferSize;
    inFile >> _numOfNod;

    while( getline(inFile,line) ){
            strWord(line);
    }

    // How to iterate over a Map
    //       map<string,vector<string> >::iterator iter = _graph.find("1");
    //       if( iter != _graph.end() )
    //           cout << "You typed '" << iter->first<< "  " << iter->second.at(1) <<endl ;

    inFile.close();
    cout << "bufferSize = " << _bufferSize << endl;
    cout << "numOfNod = " << _numOfNod << endl;

     map<string, vector<string> >::iterator iter;

     for( iter = _graph.begin(); iter != _graph.end(); ++iter ) {
          string tStri = iter->first;
          intRT(tStri);
     }

     //Now,after building our graph and workers we can build the Mailer
     _mailer = new Mailer(_workerMap,_graph,_idMap);
     sleep(1);
     //Now our Shell is only going to listen to the user and invoke "local" methods

             cout << endl;
             string inputUser;
             string argument;
             int sc_num;
             int quanta;
             while (true){
               cout << "Please choose one of the options: "<<endl;
               cout << "1 : Kill Node  "<<endl;
               cout << "2 : Revive Node  "<<endl;
               cout << "3 : Run  "<<endl;
               cout << "4 : Print RT  "<<endl;
                 cin >> inputUser;
                 if (inputUser.compare("1") == 0 ) {
                   cout << "Please enter the node ID (its node number in the graph): "<<endl;
                   cin >> argument;
//                   KillNode(argument);
                 }
                 if (inputUser.compare("2") == 0 ) {
                   cout << "Please enter the node ID (its node number in the graph): "<<endl;
                   cin >> argument;
                 //  ReviveNode(argument);
                    }
                 if (inputUser.compare("3") == 0 ) {
                   cout << "Please enter the scheduler algorithm number: "<<endl;
                    cin >> argument;
                    sc_num = atoi(argument.c_str());
                    if ((sc_num > 3) &  (sc_num < 1)){
                    	cout << "wrong scheduler number...." << endl;
                    }else{
						cout << "Please enter quanta size : "<<endl;
						cin >> argument;
						quanta = atoi(argument.c_str());
						//start(sc_num,quanta);
						sleep(1);
						_mailer->start(sc_num,quanta);
                    }
                 }
                 if (inputUser.compare("4") == 0 ) {
                	 cout << "Please enter the nodes ID: "<<endl;
                	 cin >> argument;

                	 PrintRT (argument);
                 }

                 //killall
                 //exit
                 //send packet source target text
                 if( atoi(inputUser.c_str()) > 4)
                	 cout<< "Error input, try again.... " << endl;
             }

}

void Shell::strWord( string line) {

	string buf; // Have a buffer string
	stringstream ss(line); // Insert the string into a stream

	vector<string> tVec; // Create vector to hold our nods
	int i = 0;
	string tFirst = "";

	while (ss >> buf){

		if (i == 0 && (buf.length() > 0)) {
			tFirst = buf;
		}else{
			tVec.push_back(buf);
		}
		i = i+1;
	}

	if(tFirst.compare("") != 0){
	_graph.insert( make_pair( tFirst, tVec ) );
	}
}

void Shell::intRT (string uniqueID){

  map<string, vector<string>  >::iterator it2;
  map<string,vector<string> > tMap ;// = new map<string,vector<string> >();


  for(it2 = _graph.begin(); it2 != _graph.end() ; it2++){

          vector<string> tVec;
          string tStri = (*it2).first ;
          if (tStri.compare(uniqueID) == 0 ) {
                  tVec.push_back("0");
                  tVec.push_back(tStri);
                  tMap.insert( make_pair( tStri, tVec ) );
          }
          else{
                  tVec.push_back("Infinity");
                  tVec.push_back("empty");
                  tMap.insert( make_pair( tStri, tVec ) );
          }
  }

  _nodeRT.insert( make_pair( uniqueID, tMap ) );

  //Worker tWork(tMap,uniqueID);//create new worker
  Worker *tWorker = new Worker(tMap,uniqueID);
  tWorker->setQuanta(_bufferSize);
  tWorker->setGraph(_graph);
  //_idMap.insert( make_pair(tWork.getrealID() , uniqueID ));
  //_workerMap.insert( make_pair( uniqueID, tWork ) );

  _workerMap.insert( make_pair( uniqueID, *tWorker ) );


      //tWorker->start();
  }

void Shell::run(){
			cout << "OS_092 Ass1" << endl; // prints !!!Hello World!!!

	        string inputFile;
	        cout << "Please enter setup file path: ";
	        cin >> inputFile;
	        createNet(inputFile);
}

// Incorporated in the Run command
void Shell::start(int algoNum,int quanta){

}

void Shell::PrintRT (string uniqueID){

/*  map<string, map<string, vector<string> > >::iterator it = _nodeRT.find(uniqueID);
  map<string, vector<string>  >::iterator it2;
  cout<<endl;
  if( it != _nodeRT.end() ) {
          map<string,vector<string> > tMap = it->second;

          for(it2 = tMap.begin(); it2 != tMap.end() ; it2++){
                  string tStri = (*it2).first ;
                  vector<string> tVec = (*it2).second  ;
                  cout<< tStri <<" " << tVec.at(0)<<" "<< tVec.at(1)<<" "<<endl;
          }
  }*/

	  map<string, Worker >::iterator it = _workerMap.find(uniqueID);
	  map<string, vector<string>  >::iterator it2;
	  cout<<endl;
	  if( it != _workerMap.end() ) {
	          map<string,vector<string> > tMap = it->second.getTable();

	          for(it2 = tMap.begin(); it2 != tMap.end() ; it2++){
	                  string tStri = (*it2).first ;
	                  vector<string> tVec = (*it2).second  ;
	                  cout<< tStri <<" " << tVec.at(0)<<" "<< tVec.at(1)<<" "<<endl;
	          }
	  }

}

void *functionC()
{
   pthread_mutex_lock( &mutex1 );
   counter++;
   printf("Counter value: %d\n",counter);
   pthread_mutex_unlock( &mutex1 );
}

void Shell::KillNode (string uniqueID){
         map<string,Worker >::iterator iter = _workerMap.find(uniqueID);

            if( iter != _workerMap.end() ){
         //    updateKill(uniqueID); //TODO
              //pthread_mutex_t*  m_phaseLock = &(iter->second.m_phaseLock) ;
              //pthread_mutex_lock(m_phaseLock );
              cout<<"Node : "<< uniqueID <<" has been shot!!"<<endl;
            }

      //update Mailer
}

void Shell::ReviveNode (string uniqueID){
         map<string,Worker >::iterator iter = _workerMap.find(uniqueID);

            if( iter != _workerMap.end() ) {
             //updateRevive(uniqueID);//TODO
              //pthread_mutex_t*    m_phaseLock = &(iter->second.m_phaseLock) ;
              //pthread_mutex_unlock(m_phaseLock);
              cout<<"Node : "<< uniqueID <<" is alive!!Thank you Jesus "<<endl;
              }
}


////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////// Tmp Main ////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////


